const { createClient } = require("redis");
const axios = require("axios");

class WinexAuthorizationGenerator {

    /**
     * 
     * @param {string} redisHost 
     * @param {number} redisPort 
     * @param {number} redisDb 
     */
    constructor(redisHost = "127.0.0.1", redisPort = 6379, redisDb = 0) {
        this.redisHost = redisHost;
        this.redisPort = redisPort;
        this.redisDb = redisDb;
    }

    /**
     * 
     * @param {string} redisKey 
     * @returns {Promise<{authorization:string, token:string, hospitalSOID:string, serviceHospitalSOID:string, hostname:string, employee:{employeeId:string, employeeNumber:string, employeeName:string, hospitalSOID:string, serviceHospitalSOID:string}}>}
     */
    async getAuthorization(redisKey) {
        const client = await createClient({ host: this.redisHost, port: this.redisPort }).on("error", () => { }).connect();
        await client.select(this.redisDb);
        let authorization = await client.lPop(redisKey);
        await client.rPush(redisKey, authorization);
        await client.disconnect();
        authorization = JSON.parse(authorization);
        return authorization;
    }

    /**
     * 
     * @param {string} loginUrl 
     * @param {Object} loginData 
     * @param {string} redisKey 
     * @param {number} number 
     */
    async generate(loginUrl, loginData, redisKey, number = 50) {
        const client = await createClient({ host: this.redisHost, port: this.redisPort }).on("error", () => { }).connect();
        await client.select(this.redisDb);
        await client.del(redisKey)
        for (let i = 0; i < number; i++) {
            let data = JSON.stringify(loginData);
            let config = {
                method: "post",
                maxBodyLength: Infinity,
                url: loginUrl,
                headers: {
                    "Content-Type": "application/json"
                },
                data: data,
            };
            if (config.url.startsWith("https://")) {
                config.httpsAgent = new (require("https").Agent)({ rejectUnauthorized: false });
            }
            let response = await axios.request(config);
            const authorization = {
                authorization: `Bearer ${response.data.data.access_token}`,
                token: response.data.data.access_token,
                hospitalSOID: loginData.hospitalSOID,
                serviceHospitalSOID: loginData.currentOrgId,
                hostname: new URL(loginUrl).origin
            };
            data = JSON.stringify({
                token: authorization.token
            });
            config = {
                method: "post",
                maxBodyLength: Infinity,
                url: `${authorization.hostname}/base/api/v1/base/user/get_information`,
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": authorization.authorization,
                },
                data: data,
            };
            if (config.url.startsWith("https://")) {
                config.httpsAgent = new (require("https").Agent)({ rejectUnauthorized: false });
            }
            response = await axios.request(config);
            let employee = {
                employeeId: response.data.data.employeeId,
                employeeNumber: response.data.data.employeeNo,
                employeeName: response.data.data.employeeName,
                hospitalSOID: authorization.hospitalSOID,
                hospitalName: response.data.data.hospitalName,
                serviceHospitalSOID: authorization.serviceHospitalSOID,
                serviceHospitalName: response.data.data.orgName
            };
            authorization.employee = employee;
            await client.rPush(redisKey, JSON.stringify(authorization));
        }
        await client.disconnect();
    }

}

module.exports = WinexAuthorizationGenerator;